<?php

/*
Plugin Name: WP Code Viewer
Plugin URI: http://code.google.com/p/wpcodeviewer/
Description: Utilize both GeSHi library and perl Text::VimColor module to highlight the source code
Version: 0.4
Author: RuralMoon
Author URI: http://ruralmoon.net
*/

/*

--v0.4 05/05/2007

1. change the plugin URI
2. use strict syntax to distinguish embedded close tag; for all other cases, use loose syntax

--v0.3.1 05/04/2007

standardize the code for release

--v0.3 05/03/2007
-------*******-------
check /wp-includes/formatting.php (funtion wptexturize) and you will find the code to return given text with some transformations, such as ---, -- and so on

make a new design to bypass the wordpress' text transformations, which will reserve the raw source code
v0.3 also fixed all the known bugs found in previous versions

-------*******-------

--v0.2 05/03/2007
-------*******-------
Bug Fix:
1. v0.1 can't display unicode like strings such as 0x80
2. v0.1 can't display -- correctly (wordpress' internal text transformation)
3. v0.1 will shrink the empty line, which is not desirable feature

v0.2 fixed all the three bugs mentioned above

Known Bug:
1. v0.2 use ISO-8859-1 encoding, which may not work if the code block has CJK characters (not tested yet)
2. can't bypass the wordpress internal text transformation
3. any other utf-8 like strings when doing utf-8 conversion?
-------*******-------

--v0.1 05/03/2007

*/

define('WP_CODEVIEWER_PATH', ABSPATH . '/wp-content/plugins/wp-codeviewer');
define('WP_CODEVIEWER_URL', get_bloginfo('wpurl') . '/wp-content/plugins/wp-codeviewer');
define('WP_CODEVIEWER_TMP', '/tmp');

include_once(WP_CODEVIEWER_PATH . "/geshi.php");

function wp_codeviewer_process_color($text,$type,$opt) {
      $tmpdir = WP_CODEVIEWER_TMP;

      // Trim leading and trailing linebreaks
      $text = trim($text, "\r\n");

      //case insensitive comparison
      if (strcasecmp($opt,"type") == 0) {
            $in_file = tempnam($tmpdir, 'pl');
            $out_file = tempnam($tmpdir, 'htm');

	    $handle = fopen($in_file, "w");
	    fwrite($handle, $text);
	    fclose($handle);
	    if($type){
		    $type = '--filetype '.$type;
	    }
	    system('/usr/bin/text-vimcolor --format html '.$type.' '.$in_file.' --output '.$out_file);

	    //******* log for debug
	    //system('echo "'.$in_file.' '.$out_file.'" >> '.$tmpdir.'/wp-codeviewer-debug.log');

	    $handle = fopen($out_file, "r");
	    $html = fread($handle, filesize($out_file));
	    fclose($handle);

	    //******* don't forget to delete those files!
	    unlink($out_file);
	    unlink($in_file);

	    $html = preg_replace('/\r/s','',$html);
	    $html = preg_replace('/\n/s','<br />',$html);
	    // must substitute white space, comment out below line to have a try 
	    $html = preg_replace('/  /s','&nbsp; ',$html);
	    }
	//case insensitive comparison
	//  elseif (strcasecmp($opt,"lang") == 0) {
	else {
		$geshi = new GeSHi($text,
	                       strtolower($type),
	                       WP_CODEVIEWER_PATH . "/geshi");

		$geshi->set_header_type(GESHI_HEADER_NONE);
		$html =  $geshi->parse_code() ;
	}


	return  '<div class="codeblock">'. $html .'</div>';
    }

function wp_codeviewer_arr($method,$text,$type,$alter) {
	static $arr_text = array();
	static $arr_type = array();
	static $arr_alter = array();
	if (strcmp($method,"put") == 0 ) {
	    array_push($arr_text,str_replace('\"', '"', $text));
	    array_push($arr_type,$type);
	    array_push($arr_alter,$alter);
	    return null;
	}
	//strcmp($method,"get") == 0
	else {
	    return wp_codeviewer_process_color(array_shift($arr_text),array_shift($arr_type),array_shift($arr_alter));
	}
}

function wp_codeviewer_pre_proccess($text) { 
    // Note: we use the bytes (0xFE and) 0xFF to replace the raw code block during the filtering process.
    // These bytes are not valid in UTF-8 data and thus least likely to cause problems.
    //return preg_replace('@\n<code (lang|type)="(.+?)">(.+?)\n</code>@sei', 
    return preg_replace('@<code\s+(lang|type)\s*=\s*"(.+?)"(\s+strict)?>(.+?)(?(3)\n</code>(\r?\n|$)|</code>)@sei', 
      			"'\xFF'. wp_codeviewer_arr('put','\\4','\\2','\\1')", 
			$text);
}

function wp_codeviewer_highlight($text) { 
    return preg_replace('@\xFF@se', "wp_codeviewer_arr('get','','','')", $text);
}

function wp_codeviewer_wpHead() { 
    echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"" . WP_CODEVIEWER_URL . "/style.css\" />\r\n";
}

    
// save code block at the very beginning before wordpress' internal text transformation
add_filter('the_content', 'wp_codeviewer_pre_proccess', -1000);
// process the code block at the very end
add_filter('the_content', 'wp_codeviewer_highlight', 1000);
// add stylesheet to the header
add_filter('wp_head','wp_codeviewer_wpHead');

?>
